a second thread preempts the first & updates the value,
the first thread continues its work and it has a stale value.
It is actually worse
++value turns into 7 byte-codes:
Assume the value field has a value of 42
Byte-code
Description
Operand Stack After
aload 0
Load local variable 0 onto the stack. In a non-static method, local variable 0 is always the "this" pointer, or the object that received the most recent message.
this
dup
Place a copy of the top operand on the operand stack back onto the operand stack.
this, this
getfield value
Retrieve the field named "value" from the object pointed to on the top of the operand stack, which is "this". Put the resulting value back on to the top of the operand stack.
this, 42
iconst_1
Put the constant value 1 onto the operand stack.
this, 42, 1
iadd
Perform integer addition on the top two items on the operand stack and place the result back on the operand stack.
this, 43
putfield value
Put the top item on the stack (43) in the "value" field of the object pointed to by the next to top item on the operand stack (this).
<<empty>>
return
Return back to the place where this method was called.
How Many Possibilities?
Assume the following:
Two threads
One instance of ObjectWithValue
Both calling incrementValue()
Answer the following:
How many possible ways can those two threads execute?
What are the possible results?
Answers
How many possible orderings?
3,432
How can we calculate it?
Assuming no looping/branching
All instructions executed through to completion
All threads complete
N = Number of instructions
T = Number of threads
How many possible outcomes?
2
value incremented by 2
value incremented by 1
How?
Sharing Without Guarding
@Test
publicvoid singleThreaded()throwsInterruptedException{Thread t = newThread(incrementValue);
t.start();
t.join();
assertEquals(10000, object.getValue());}
@Test
publicvoid multipleThreadsFail()throwsInterruptedException{Thread[] threads = newThread[5];for(int i = 0; i < threads.length; ++i)
threads[i] = newThread(incrementValue);for(Thread t : threads) t.start();for(Thread t : threads) t.join();
assertTrue("Expected 10000, actual: " + object.getValue(),
50000 == object.getValue());}
When It's Quiet Be Afraid, Very Afraid
Quick Quiz. Is this code MT Safe?
What's Happening?
++value is actually three operations:Since a thread can be preempted at any time…
It is actually worse
++value turns into 7 byte-codes:How Many Possibilities?
Assume the following:Two threads
Answer the following:
Answers
How many possible orderings?How can we calculate it?
How many possible outcomes?
How?
Sharing Without Guarding
Demo
Let’s demonstrate that this code is broken<--Back | ^Top^ | Next-->